#include "main.h"

int on_option_f( const char *filename, void *args )
{
	mds_options *options = args;
	fprintf( stderr, "<< INSERTING options from file '%s' >>\n", filename );
	if( mds_options_load( options, filename, "f") < 0 )
	{
		mds_perror( stderr, "mds_options_load(%s)", filename );
		return -1;
	}
	return 0;
}


int on_option_dt_sim( const char *value, void *args )
{
	Real *dt = args;
	*dt = strtod(value, NULL);
	if( *dt <= 0 )
	{
		fprintf( stderr, "** invalid dt_sim <= 0\n" );
		return -1;
	}
	return 0;
}


int on_option_dt_out(  const char *value, void *args )
{
	Real *t_out = args;
	*t_out = strtod( value, NULL);
	if( *t_out <= 0 )
	{
		fprintf( stderr, "** invalid dt_out <= 0\n" );
		return -1;
	}
	return 0;
}

int on_option_t_max( const char *value, void *args )
{
	Real *t_max = args;
	*t_max = strtod( value, NULL);
	return 0;
}

int on_option_id( const char *value, void *args )
{
	const char **pId = args;
	*pId = value;
	return 0;
}

/*
int on_option_np( const char *value, void *args )
{
	size_t *np = args;
	*np = strtol( value, NULL, 10);
	if( *np <= 0 )
	{
		fprintf( stderr, "** invalid #particles\n" );
		return -1;
	}
	return 0;
}
 */


int on_option_step( const char *value, void *args )
{
	mds_step_type *st = args;
	
	if( !strcmp( value, "verlet" ) )
	{
		*st = MDS_STEP_VERLET;
		return 0;
	}
	
	if( !strcmp( value, "beeman" ) )
	{
		*st = MDS_STEP_BEEMAN;
		return 0;
	}
	
	fprintf( stderr, "** unknown step '%s'", value );
	return -1;
}

int on_option_cutoff( const char *value, void *args )
{
	Real *cutoff = args;
	*cutoff = strtod( value, NULL);
	if( *cutoff <= 0 )
	{
		fprintf( stderr, "** invalid cutoff\n" );
		return -1;
	}
	return 0;
}

int on_option_cutout( const char *value, void *args )
{
	Real *cutout = args;
	*cutout = strtod( value, NULL);
	if( *cutout <= 0 )
	{
		fprintf( stderr, "** invalid cutout\n" );
		return -1;
	}
	return 0;
}

int on_option_dyn( const char *value, void *args )
{
	mds_dyn_type *dyn = args;
	
	if( strcmp( value, "full" ) == 0 ) 
	{
		*dyn = MDS_DYN_FULL;
		return 0;
	}
	
	if( strcmp( value, "cell" ) == 0 )
	{
		*dyn = MDS_DYN_CELL;
		return 0;
	}
	
	fprintf( stderr, "** invalid dyn '%s'\n", value );
	return -1;
}

int on_option_run( const char *value, void *args )
{
	mds_run_type *run = args;
	
	if( strcmp( value, "NVE" ) == 0 )
	{
		*run = MDS_RUN_NVE;
		return 0;
	}
	
	if( strcmp( value, "NVT" ) == 0 )
	{
		*run = MDS_RUN_NVT;
		return 0;
	}
	
	fprintf( stderr, "** invalid run type '%s'\n", value );
	return -1;
}


#define BENCH_FMT "%u %.4e\n"

typedef struct bench_tag_
{
	struct bench_tag_ *next, *prev;
	size_t np;
	double tm;
} bench_t;

typedef struct
{
	bench_t *head;
	bench_t *tail;
	size_t   size;
} bench_list_t;

void _add_to_benchmark( const char *BENCHFILE, size_t np, double tm )
{
	FILE         *fp   = fopen( BENCHFILE, "rb" );
	bench_list_t  blist = MDS_LIST_INIT;
	if( fp )
	{
		/*----------------------------------------------------------------------
		 * load
		 *--------------------------------------------------------------------*/
		char buffer[256];
		int  found = 0;
		memset(buffer,0,sizeof(buffer));
		while( NULL != fgets(buffer,sizeof(buffer)-1,fp) )
		{
			unsigned n = 0;
			double   f = 0;
			if( sscanf( buffer, "%u %lg", &n, &f) == 2)
			{
				bench_t *node = MDS_CALLOC_AS(bench_t,1);
				/* fprintf( stderr, "bench: %u %g\n", n, f ); */
				if( node )
				{
					node->np = n;
					if( np == node->np )
					{
						node->tm = 0.5 * ( tm + f );
						found = 1;
					}
					else
						node->tm = f;
					mds_list_push_back( &blist, node );
					
				}
				else 
				{
					fclose(fp); fp = NULL;
					goto ADD_END;
				}
			}
			
		}
		fclose(fp); fp = NULL;
		
		/*----------------------------------------------------------------------
		 * save
		 *--------------------------------------------------------------------*/
		fp = fopen( BENCHFILE, "wb" );
		if( !fp )
		{
			goto ADD_END;
		}
		else 
		{
			const bench_t *node = blist.head;
			while( node != NULL )
			{
				fprintf( fp, BENCH_FMT, (unsigned)(node->np), node->tm);
				node = node->next;
			}
			if( !found )
			{
				fprintf( fp, BENCH_FMT, (unsigned) np, tm );
			}
			fclose(fp);
			fp = NULL;
			
		}
		
	}
	else
	{
		/*----------------------------------------------------------------------
		 * first write/overwrite
		 *--------------------------------------------------------------------*/
		fp = fopen( BENCHFILE, "wb" );
		if( fp )
		{
			fprintf( fp, BENCH_FMT, (unsigned) np, tm );
			fclose( fp ); fp = NULL;
		}
	}
	
ADD_END:
	assert( NULL == fp );
	while(blist.size>0)
	{
		MDS_FREE_AS(bench_t, mds_list_pop_back(bench_t, &blist)  ,1);
	}
}

